
#pragma once

#include "primitive_iterator.h"
#include "variant_step.h"


namespace tools{
    namespace variant_detail{

//--------------------------------------------------------------------------------------

        template<class T, int CONTAINER_CATEGORY>struct OutIterator;

//--------------------------------------------------------------------------------------

        template<class T>struct OutIterator<T, ePRIMITIVE>
        {
            static Native GetIterator(void* variant, bool beg)
            {
                typedef PrimitiveIterator<Variant> Primitive;
                Variant& v = *static_cast<Variant*>(variant);
                Primitive primitive(v);

                if(!beg)
                    ++primitive;

                return Step< Primitive, DIRECT_NORMAL,ePRIMITIVE>( primitive );
            }
            static Native GetConstIterator(const void* variant, bool beg)
            {
                typedef PrimitiveIterator<const Variant> Primitive;
                const Variant& v = *static_cast<const Variant*>(variant);
                Primitive primitive(v);

                if(!beg)
                    ++primitive;

                return Step< Primitive, DIRECT_NORMAL,ePRIMITIVE>( primitive );
            }        
        };

//--------------------------------------------------------------------------------------

        template<class T>struct OutIterator<T, eLINEAR>
        {
            static Native GetIterator(void* variant, bool beg)
            {
                Variant& var = *static_cast<Variant*>(variant);
                if(beg)
                    return Step< typename T::iterator, DIRECT_NORMAL,eLINEAR>( var.template Get<T>().begin() );
                return Step< typename T::iterator, DIRECT_NORMAL,eLINEAR>( var.template Get<T>().end() );
            }
            static Native GetConstIterator(const void* variant, bool beg)
            {
                const Variant& var = *static_cast<const Variant*>(variant);
                if(beg)
                    return Step< typename T::const_iterator, DIRECT_NORMAL,eLINEAR>( var.template Get<T>().begin() );
                return Step< typename T::const_iterator, DIRECT_NORMAL,eLINEAR>( var.template Get<T>().end() );
            }        
        };
//--------------------------------------------------------------------------------------

        template<class T>struct OutIterator<T, eASSOCIATIVE>
        {
            static Native GetIterator(void* variant, bool beg)
            {
                Variant& var = *static_cast<Variant*>(variant);
                if(beg)
                    return Step< typename T::iterator, DIRECT_NORMAL,eASSOCIATIVE>( var.template Get<T>().begin() );
                return Step< typename T::iterator, DIRECT_NORMAL,eASSOCIATIVE>( var.template Get<T>().end() );
            }
            static Native GetConstIterator(const void* variant, bool beg)
            {
                const Variant& var = *static_cast<const Variant*>(variant);
                if(beg)
                    return Step< typename T::const_iterator, DIRECT_NORMAL,eASSOCIATIVE>( var.template Get<T>().begin() );
                return Step< typename T::const_iterator, DIRECT_NORMAL,eASSOCIATIVE>( var.template Get<T>().end() );
            }        
        };
//--------------------------------------------------------------------------------------

    }//namespace variant_detail
}//namespace tools


